#pragma once
#pragma warning( disable: 4251 ) 

//WGLENGINE_DLL
#ifdef WGLENGINE_DLL
#define WGLENGINE_EXPORT __declspec(dllexport)
#else
#define WGLENGINE_EXPORT __declspec(dllimport)
#endif

#include <string>
#include <vector>

#include "GL/glew.h"

class Material;
class Shader;
class SceneNode;
class WGLENGINE_EXPORT SceneMesh
{
protected:
	virtual void RenderMesh(int pass);

	//draw ID - used for binding to the right uniform block
	//Current uniform block is a huge block that contains matrices for all objects, so we need an offset
	//to know which matrices are for which object
	int drawID;

	//reference to a parent node in scenegraph
	std::weak_ptr<SceneNode> parentNode;

	//arrays for position normal and uv
	std::unique_ptr<unsigned int[]> indexArray;
	std::unique_ptr<float[]> vertexPosArray;
	std::unique_ptr<float[]> vertexNormArray;
	std::unique_ptr<float[]> vertexUVArray;
	std::unique_ptr<float[]> vertexColorArray;

	std::unique_ptr<unsigned int[]> vertexDrawIDArray;

	std::unique_ptr<GLuint[]> vboIDs;
	GLuint iboID;
	GLuint vaoID;

	static int meshCreated;								//!< mesh count in the entire scene, for making drawID
	
	std::shared_ptr<Material> mat;
	int numOfTriangles;
	bool initiated;										//!< vao initiated in render context
	bool enabled;

	enum MeshData 
	{
		POSITION = 0x01, 
		NORMAL = 0x02, 
		INDEX = 0x04,
		UV0 = 0x08, 
		UV1 = 0x10,
		UV2 = 0x20,
		UV3 = 0x40,
		UV4 = 0x80,
		COLOR = 0x100
	};

	int meshType;

public:
	SceneMesh(std::string material = "");
	~SceneMesh();

	virtual void GenVBO();

	void CreateIndexArray(int length)
	{
		indexArray = std::unique_ptr<unsigned int[]>(new unsigned int[length]);
		numOfTriangles = length / 3;
	}
	void CreateVertexArray(int length)
	{
		int posArraySize = length * 3;
		vertexPosArray = std::unique_ptr<float[]>(new float[posArraySize]);

		if((meshType & SceneMesh::NORMAL) > 0)
		{
			vertexNormArray = std::unique_ptr<float[]>(new float[posArraySize]);
		}

		if((meshType & SceneMesh::COLOR) > 0)
		{
			int colorArraySize = length * 4;
			vertexColorArray = std::unique_ptr<float[]>(new float[colorArraySize]);
		}

		if((meshType & SceneMesh::UV0) > 0)
		{
			int uvArraySize = length * 2;
			vertexUVArray = std::unique_ptr<float[]>(new float[uvArraySize]);
		}

		int drawIDArraySize = length * 1;
		vertexDrawIDArray = std::unique_ptr<unsigned int[]>(new unsigned int[drawIDArraySize]);
		for(int i=0; i<drawIDArraySize; i++)
		{
			vertexDrawIDArray[i] = drawID;
		}
	}

	void SetIndexArray(int index, unsigned int val)
	{
		indexArray[index] = val;
	}

	void SetVertexArray(int index, float val)
	{
		vertexPosArray[index] = val;
	}

	void SetNormalArray(int index, float val)
	{
		vertexNormArray[index] = val;
	}

	void SetUVArray(int index, float val)
	{
		vertexUVArray[index] = val;
	}
	
	void SetColorArray(int index, float val)
	{
		vertexColorArray[index] = val;
	}

	void SetParent(std::shared_ptr<SceneNode> node)
	{
		this->parentNode = node;
	}

	int GetDrawID()
	{
		return drawID;
	}

	void Render(int pass);


};